import { addEvent } from './event'

/**
 *
 * @param {*} vnode 虚拟节点
 * @param {*} container 要把虚拟dom转换真实dom并插入到那个容器中去
 */

function render(vnode, container) {
  const dom = createDOM(vnode)
  container.appendChild(dom)
}

export function createDOM(vdom) {
  if (typeof vdom === 'string' || typeof vdom === 'number') {
    return document.createTextNode(vdom)
  }
  //除去简单数据类型的数据
  const { type, props } = vdom
  let dom
  if (typeof type === 'function') {
    if (type.isReactComponent) {
      return mountClassComponent()
    } else {
      return mountFunctionComponent(vdom)
    }
  } else {
    dom = document.createElement(type)
  }

  //使用虚拟dom的属性 来更新新的dom属性
  updateProps(dom, props)

  if (
    typeof props.children === 'string' ||
    typeof props.children === 'number'
  ) {
    dom.textContent = props.children
  } else if (typeof props.children === 'object' && props.children.type) {
    render(props.children, dom)
  } else if (Array.isArray(props.children)) {
    reconclieChildren(props.children, dom)
  } else {
    document.textContent = props.children ? props.children.toString() : ''
  }
  // vdom.dom = dom
  return dom
}

/**
 *
 * @param {*} dom
 * @param {*} newProps
 */

function updateProps(dom, newProps) {
  for (let key in newProps) {
    if (key === 'children') continue
    if (key === 'style') {
      let styleObj = newProps.style
      for (let attr in styleObj) {
        dom.style[attr] = styleObj[attr]
      }
    } else if (key.startsWith('on')) {
      // dom[key.toLocaleLowerCase()] = newProps[key]
      addEvent(dom, key.toLocaleLowerCase(), newProps[key])
    } else {
      dom[key] = newProps[key]
    }
  }
}

/**
 *
 * @param {*} childrenVdom 虚拟dom的儿子们
 * @param {*} parenDOM 父亲的真实dom
 */

function reconclieChildren(childrenVdom, parenDOM) {
  for (let i = 0; i < childrenVdom.length; i++) {
    let chiildVdom = childrenVdom[i]
    render(chiildVdom, parenDOM)
  }
}

const ReactDom = { render }

export default ReactDom

/**
 *
 * @param {*} vdom 把一个函数组件转换成为数据类型dom
 */
function mountFunctionComponent(vdom) {
  const { type: FunctionComponent, props } = vdom
  let renderVdom = FunctionComponent(props)
  return createDOM(renderVdom)
}

/**
 *
 * @param {*} vdom 把一个函数组件转换成为数据类型dom
 * @returns
 */
function mountClassComponent(vdom) {
  let { type, props } = vdom
  let classInstance = new type()
  //生命周期函数
  classInstance.componentWillMout && classInstance.componentWillMout()
  let renderVdom = classInstance.render()
  let dom = createDOM(renderVdom)
  classInstance.oldRenderVdom = renderVdom //实例上绑定老的渲染节点
  classInstance.componentDidMount &&
    classInstance.componentDidMount.bind(classInstance)
  classInstance.dom = dom
  return dom
}
